package br.usp.ime.origami.algorithms;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import br.usp.ime.origami.model.MovingPoint;
import br.usp.ime.origami.model.MovingTriangle;
import br.usp.ime.origami.model.SimplePolygon;
import br.usp.ime.origami.primitives.TriangulationPrimitives;

public class Triangulation {

    private static final Logger logger = Logger.getLogger(Triangulation.class);

    private SimplePolygon polygon;

    private List<MovingTriangle> triangles;

    public Triangulation(SimplePolygon polygon) {
        this.polygon = polygon;
    }

    public List<MovingTriangle> getTriangles() {
        if (triangles == null) {
            this.triangularize();
        }
        return triangles;
    }

    private void triangularize() {
        // algorithm: otectomy (orourke 39)
        this.triangles = new ArrayList<MovingTriangle>();
        List<MovingPoint> points = polygon.toMovingPoints();

        while (points.size() > 3) {
            boolean earFound = false;
            for (int i = 0; i < points.size(); i++) {
                logger.info("testing ear " + i + " total points:" + points.size());

                earFound = TriangulationPrimitives.isEar(i, points);
                if (earFound) {
                    int before = (i - 1 + points.size()) % points.size();
                    int after = (i + 1) % points.size();

                    MovingTriangle triangle = new MovingTriangle(points.get(before), points.get(i), points.get(after));
                    this.triangles.add(triangle);

                    logger.info("extracting " + triangle + ", removing " + points.get(i));
                    points.remove(i);
                    break;
                }
            }
            assert earFound : "a polygon always has 2 ears (I dont remember the paper author).";
        }

        logger.info("adding last triangle");

        this.triangles.add(new MovingTriangle(points.get(0), points.get(1), points.get(2)));
        assert triangles.size() == polygon.getPoints().size() - 2 : triangles.size() + " triangles found in"
                + "triangulation, expecting " + (polygon.getPoints().size() - 2);
    }

}
